/*
does not use built-in detection functionality

#alert tcp $EXTERNAL_NET $HTTP_PORTS -> $HOME_NET any (msg:"WEB-CLIENT Malicious PICT file download"; flow:established,to_client; content:"|00 11 02 FF 0C 00|"; reference:cve,2008-3021; reference:url ,technet.microsoft.com/en-us/security/bulletin/ms08-044; metadata:service http, policy security-ips drop; policy balanced-ips drop; classtype: attempted-user; sid:13946; rev:1;)
*/


/*
 * Use at your own risk.
 *
 * Copyright (C) 2005-2008 Sourcefire, Inc.
 * 
 * This file is autogenerated via rules2c, by Brian Caswell <bmc@sourcefire.com>
 */

#include "sf_snort_plugin_api.h"
#include "sf_snort_packet.h"

#include "so-util.h"

/* declare detection functions */
int rule13946eval(void *p);

/* declare rule data structures */
/* precompile the stuff that needs pre-compiled */
/* flow:established, to_client; */
static FlowFlags rule13946flow0 = 
{
    FLOW_ESTABLISHED|FLOW_TO_CLIENT
};

static RuleOption rule13946option0 =
{
    OPTION_TYPE_FLOWFLAGS,
    {
        &rule13946flow0
    }
};
// content:"|00 11 02 FF 0C 00|"; 
static ContentInfo rule13946content1 = 
{
    (uint8_t *) "|00 11 02 FF 0C 00|", /* pattern (now in snort content format) */
    0, /* depth */
    0, /* offset */
    CONTENT_BUF_NORMALIZED, /* flags */ // XXX - need to add CONTENT_FAST_PATTERN support
    NULL, /* holder for boyer/moore PTR */
    NULL, /* more holder info - byteform */
    0, /* byteform length */
    0 /* increment length*/
};

static RuleOption rule13946option1 = 
{
    OPTION_TYPE_CONTENT,
    {
        &rule13946content1
    }
};

/* references for sid 13946 */
/* reference: cve "2008-3021"; */
static RuleReference rule13946ref1 = 
{
    "cve", /* type */
    "2008-3021" /* value */
};

/* reference: url "technet.microsoft.com/en-us/security/bulletin/ms08-044"; */
static RuleReference rule13946ref2 = 
{
    "url", /* type */
    "technet.microsoft.com/en-us/security/bulletin/ms08-044" /* value */
};

static RuleReference *rule13946refs[] =
{
    &rule13946ref1,
    &rule13946ref2,
    NULL
};
/* metadata for sid 13946 */
/* metadata:service http, policy balanced-ips drop, policy security-ips drop; */
static RuleMetaData rule13946service1 = 
{
    "service http"
};

static RuleMetaData rule13946policy1 =
{
   "policy max-detect-ips drop"
};

static RuleMetaData *rule13946metadata[] =
{
    &rule13946service1,
    &rule13946policy1,
    NULL
};
RuleOption *rule13946options[] =
{
    &rule13946option0,
    &rule13946option1,
    NULL
};

Rule rule13946 = {
   
   /* rule header, akin to => tcp any any -> any any               */{
       IPPROTO_TCP, /* proto */
       "$EXTERNAL_NET", /* SRCIP     */
       "$HTTP_PORTS", /* SRCPORT   */
       0, /* DIRECTION */
       "$HOME_NET", /* DSTIP     */
       "any", /* DSTPORT   */
   },
   /* metadata */
   { 
       3,  /* genid (HARDCODED!!!) */
       13946, /* sigid */
       11, /* revision */
   
       "attempted-user", /* classification */
       0,  /* hardcoded priority XXX NOT PROVIDED BY GRAMMAR YET! */
       "FILE-IMAGE Apple PICT/Quickdraw image converter packType 4 buffer overflow exploit attempt",     /* message */
       rule13946refs /* ptr to references */
       ,rule13946metadata
   },
   rule13946options, /* ptr to rule options */
   &rule13946eval, /* use the built in detection function */
   0 /* am I initialized yet? */
};


/* detection functions */
int rule13946eval(void *p) {
    const uint8_t *beg_of_payload, *end_of_payload;
    const uint8_t *cursor_normal = 0;
    uint16_t packType = 0;
    uint16_t pixelSize = 0;

    SFSnortPacket *sp = (SFSnortPacket *) p;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_client;
    if (checkFlow(p, rule13946options[0]->option_u.flowFlags) > 0 ) {
        // content:"|00 11 02 FF 0C 00|";
        if (contentMatch(p, rule13946options[1]->option_u.content, &cursor_normal) > 0) {

            if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
                return RULE_NOMATCH;

           // for the current vuln, the maximum offset from opCode is 35 bytes (case 0x9A
           // and 0x9B below). 
            while (cursor_normal < end_of_payload) {
                // opCode, packType and pixelSize are big-endian
                // looking for 0x009[0,1,8-B]
                if (*cursor_normal == 0) {
                    if(cursor_normal + 31 >= end_of_payload)
                       return RULE_NOMATCH;

                    // packType = 4 and pixelSize = 0
                    switch (*(cursor_normal+1)) {
                        case 0x90: // BitsRect
                        case 0x91: // BitsRgn
                        case 0x98: // PackBitsRect
                        case 0x99: // PackBitsRgn
                             packType  = read_big_16(cursor_normal+14);
                             pixelSize = read_big_16(cursor_normal+30);
                             if (packType == 0x0004 && pixelSize == 0x0000) return RULE_MATCH;
                        break;
                        case 0x9A: // DirectBitsRect
                        case 0x9B: // DirectBitsRgn
                             if(cursor_normal + 35 >= end_of_payload)
                                return RULE_NOMATCH;
                             packType  = read_big_16(cursor_normal+18);
                             pixelSize = read_big_16(cursor_normal+34);
                             if (packType == 0x0004 && pixelSize == 0x0000) return RULE_MATCH;
                        break;
                    }
                }
                cursor_normal++;
            }
        }
    }
    return RULE_NOMATCH;
}

/*
Rule *rules[] = {
    &rule13946,
    NULL
};
*/
